package itsecurity.cert;

import iaik.asn1.structures.AlgorithmID;
import iaik.pkcs.pkcs7.DigestInfo;
import iaik.security.provider.IAIK;

import java.io.File;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Security;
import java.security.SignatureException;
import java.util.StringTokenizer;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

/**
 * Creates signed X509-certificate from given byte string of 
 * syntax "xx xx xx" where xx is a hex-value
 *
 */
public class Signer {

	/**
	 * 
	 * @param args One byte string of syntax "xx xx xx" where xx is a hex-value
	 */
	public static void main(String[] args) {
		
		try {
	    Security.insertProviderAt(new IAIK(), 2);
	    Security.insertProviderAt(new MDBProvider(), 3);
	  } catch( Throwable e ) {
	    //
	  }
		
		StringTokenizer st = new StringTokenizer(args[1]," ",false);
	  String str="";
	  while (st.hasMoreElements()) str += st.nextElement();
	  
	  byte[] data = iaik.utils.Util.toByteArray(str);

		byte [] signature=null;
	  try { 
	  	signature = Signer.sign(data);
		} catch (SignatureException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("Signature in bytes is (hex values): \n"+
				iaik.utils.Util.toString(signature));
	}
	
	
	public static byte[] sign(byte [] argument) throws SignatureException {
		
		File file=new File(KeyManager.KEYSTORE);
//		file.createNewFile();
   	AlgorithmID algorithm = new AlgorithmID("1.3.6.1.4.1.2706.4.1.2", "mdbWithRSAEncryption");
   	PrivateKey privateKey = KeyManager.getKeyPair("Circus Authorities", "Bob".toCharArray(), file).getPrivate();
   	MessageDigest digestive = null;
		// Compute digest
		try {
			digestive = MessageDigest.getInstance("MDB");
		} catch (NoSuchAlgorithmException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		digestive.update(argument);
		byte[] digested = digestive.digest();
		byte[] digest_info = null;
		
		AlgorithmID mdb = new AlgorithmID("1.3.6.1.4.1.2706.4.1.1", "MDB");
		DigestInfo digested_info = new DigestInfo(mdb, digested);
		digest_info = digested_info.toByteArray();
		//System.out.println("digest_info= " + digested_info);
		// DER encode DigestInfo - object (first transform it to ASN1Object):
		// DER_encoded_digest_info = iaik.asn1.DerCoder.encode(digested_info.toASN1Object()); // THIS IS NOT REALLY NEEDED!
		
		//System.out.println("DER_encoded_digest_info= " + iaik.utils.Util.toString(DER_encoded_digest_info));
		
		// Encrypt digest
		Cipher cipher = null;
		try {
			cipher = Cipher.getInstance("RSA");
		} catch (NoSuchAlgorithmException e3) {
			// TODO Auto-generated catch block
			e3.printStackTrace();
		} catch (NoSuchPaddingException e3) {
			// TODO Auto-generated catch block
			e3.printStackTrace();
		}
		try {
			cipher.init(Cipher.ENCRYPT_MODE, privateKey);
		} catch (InvalidKeyException e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
		
		byte[] signature = null;
		
		try {
			//signature = cipher.doFinal(DER_encoded_digest_info);
			signature = cipher.doFinal(digest_info);
		} catch (IllegalBlockSizeException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (BadPaddingException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		return signature;
	}


}
